package tw.cuttle.core;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;

import tw.cuttle.bean.Action;
import tw.cuttle.bean.ActionException;
import tw.cuttle.bean.Actions;
import tw.cuttle.bean.Cache;
import tw.cuttle.bean.Env;
import tw.cuttle.bean.Form;
import tw.cuttle.bean.Forms;
import tw.cuttle.bean.Global;
import tw.cuttle.bean.Layout;
import tw.cuttle.bean.Process;
import tw.cuttle.bean.ProcessException;
import tw.cuttle.bean.Resource;
import tw.cuttle.bean.Resources;
import tw.cuttle.bean.Setting;
import tw.cuttle.bean.Template;

public class CuttleConfigurationParser {
	private static Log log=LogFactory.getLog(CuttleConfigurationParser.class);
    public enum TYPE{
	noNS, NS
    }
    public static Actions parseAction(Document doc){
    	log.info("...in");
	try {
	    OutputFormat format = new OutputFormat(doc);
	        format.setLineWidth(65);
	        format.setIndenting(true);
	        format.setIndent(2);
	        XMLSerializer serializer = new XMLSerializer(System.out, format);
	        serializer.serialize(doc);
	    Actions actions=new Actions();
	    List<Action> actionList=new ArrayList<Action>();
	    NodeList nodeList=doc.getElementsByTagName("Action");
	    for(int i=0;i<nodeList.getLength();i++){
		Element element=(Element)nodeList.item(i);

		if(nodeList.item(i).getNodeType()==Node.ELEMENT_NODE){
		   
	        actionList.add(getAction(element, TYPE.noNS.name()));
		}
	    }
	    actions.setActions(actionList);
	    return actions;
	} catch (Exception e) {
	    e.printStackTrace();
	    throw new RuntimeException(e);
	}
    }
    public static Actions getActions(Element element){
	System.out.println("in getActions");
	Actions actions=new Actions();
	NodeList actionNodes=element.getElementsByTagNameNS("*", "Action");
	System.out.println("actionNodes:"+actionNodes);
	System.out.println("actionNodes.length:"+actionNodes.getLength());
	List<Action> actionList=new ArrayList<Action>();
	for(int i=0;i<actionNodes.getLength();i++){
	    Node actionNode=actionNodes.item(i);
	    if(actionNode.getNodeType()==Node.ELEMENT_NODE){
		Element e=(Element)actionNode;
		Action action=getAction(e, TYPE.NS.name());
		actionList.add(action);
		System.out.println("action id in cuttleConfiguration parser:"+action.getId());
	    }
	}
	
	actions.setActions(actionList);
	return actions;
    }
    private static NodeList getNodeListByTagName(Element e, String tagName,  String type){
	if(type.equals(TYPE.noNS.name())){
	    return e.getElementsByTagName(tagName);
	}else{
	    return e.getElementsByTagNameNS("*", tagName);
	}
    }
    public static Action getAction(Element element, String nsType){
	System.out.println("child length:"+element.getChildNodes().getLength());
	Action action=new Action();
	String ajaxExtend=element.getAttribute("ajaxExtend");
	String extend=element.getAttribute("extend");
	String form=element.getAttribute("form");
	String id=element.getAttribute("id");
	String layout=element.getAttribute("layout");
	String group=element.getAttribute("group");
	String name=element.getAttribute("name");
	String description=element.getAttribute("description");
	String authType=element.getAttribute("authType");
	String preExec=element.getAttribute("preExec");
	if(group.length()>0)action.setGroup(group);
	if(name.length()>0)action.setName(name);
	if(description.length()>0)action.setDescription(description);
	if(authType.length()>0)action.setAuthType(authType);
	if(ajaxExtend.length()>0)action.setAjaxExtend(ajaxExtend);
	if(extend.length()>0)action.setExtend(extend);
	if(form.length()>0)action.setForm(form);
	if(preExec.length()>0)action.setPreExec(preExec);
	action.setId(id);
	if(layout.length()>0)action.setLayout(layout);

	NodeList processNodes=getNodeListByTagName(element, "Process", nsType);

	for(int i=0;i<processNodes.getLength();i++){

	    Node processNode=processNodes.item(i);
	    if(processNode.getNodeType()==Node.ELEMENT_NODE){
		
		Element processElement=(Element) processNode;
		Process process=new Process();
		if(processElement.getAttribute("exec").length()>0)process.setExec(processElement.getAttribute("exec"));
		process.setId(processElement.getAttribute("id"));
		if(processElement.getAttribute("view").length()>0)process.setView(processElement.getAttribute("view"));
		if(processElement.getAttribute("viewType").length()>0)process.setViewType(processElement.getAttribute("viewType"));

		NodeList children = processElement.getChildNodes();
                for (int j = 0; j < children.getLength(); j++) {
                    Node childNode = children.item(j);
                    if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                        Element child = (Element) childNode;
                        if(child.getNodeName()!=null)
                        if (child.getNodeName().equals("Cache")) {
                            Cache cache=new Cache();
                            String appendParameter=child.getAttribute("appendParameter");
                            String _id=child.getAttribute("id");
                            String type=child.getAttribute("type");
                            String timeout=child.getAttribute("timeout");
                            if(appendParameter.length()>0)cache.setAppendParameter(appendParameter);
                            cache.setId(_id);
                            if(type.length()>0)cache.setType(type);
                            if(timeout.length()>0)cache.setTimeout(Integer.parseInt(timeout));
                            process.setCache(cache);
                        }else if(child.getNodeName().equals("processException")){
                            ProcessException pe=new ProcessException();
                            String _id=child.getAttribute("id");
                            String type=child.getAttribute("type");
                            String exec=child.getAttribute("exec");
                            String view=child.getAttribute("view");
                            String viewType=child.getAttribute("viewType");
                            pe.setExec(exec);
                            pe.setId(_id);
                            pe.setType(type);
                            pe.setView(view);
                            pe.setViewType(viewType);
                            if(process.getExceptions()==null)process.setExceptions(new ArrayList<ProcessException>());
                            process.getExceptions().add(pe);
                        }
                    }
                   
                }
                action.addProcess(process);
	    }
	}
	
	NodeList aeNodes=getNodeListByTagName(element, "ActionException", nsType);
	for(int i=0;i<aeNodes.getLength();i++){
	    Node aeNode=aeNodes.item(i);
	    if(aeNode.getNodeType()==Node.ELEMENT_NODE){
		Element aeElement=(Element) aeNode;
		ActionException ae=new ActionException();
		String actionForward=aeElement.getAttribute("actionForward");
		String _id=aeElement.getAttribute("id");
		String type=aeElement.getAttribute("type");
		ae.setActionForward(actionForward);
		ae.setId(_id);
		ae.setType(type);
		action.addException(ae);
	    }
	}
	return action;
    }
    public static Setting getSetting(Element element) {
        Setting setting = new Setting();

        NodeList layoutNodes = element.getElementsByTagNameNS("*", "Layout");
        for (int i = 0; i < layoutNodes.getLength(); i++) {
            Node layoutNode = layoutNodes.item(i);
            if (layoutNode.getNodeType() == Node.ELEMENT_NODE) {
                Element layoutElement = (Element) layoutNode;
                Layout layout = new Layout();

                NodeList children = layoutElement.getChildNodes();
                for (int j = 0; j < children.getLength(); j++) {
                    Node childNode = children.item(j);
                    if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                        Element child = (Element) childNode;
                        if (child.getLocalName().equals("Template")) {
                            Template template = new Template();
                            if(child.getAttribute("default").length()>0)template.setDefault(Boolean.parseBoolean(child.getAttribute("default")));
                            template.setView((child.getAttribute("view")));
                            template.setId((child.getAttribute("id")));
                           
                            layout.addTemplate(template);
                        
                        }
                    }
                }

                setting.setLayout(layout);
            }
        }

        NodeList envs = element.getElementsByTagNameNS("*", "Env");
        for (int i = 0; i < envs.getLength(); i++) {
            Node envNode = envs.item(i);
            if (envNode.getNodeType() == Node.ELEMENT_NODE) {
                Element envElement = (Element) envNode;
                Env env=new Env();
                env.setStrategy(envElement.getAttribute("strategy"));
                if(envElement.getAttribute("cacheFolder").length()>0)env.setCacheFolder(envElement.getAttribute("cacheFolder"));
                if(envElement.getAttribute("enableCache").length()>0)env.setEnableCache(Boolean.parseBoolean(envElement.getAttribute("enableCache")));
                if(envElement.getAttribute("helper").length()>0)env.setHelper(envElement.getAttribute("helper"));
                setting.setEnv(env);
            }
        }
        
        NodeList resources = element.getElementsByTagNameNS("*", "Resources");
        for (int i = 0; i < resources.getLength(); i++) {
            Node resourcesNode = resources.item(i);
            if (resourcesNode.getNodeType() == Node.ELEMENT_NODE) {
                Element resourcesElement = (Element) resourcesNode;
                Resources rs=new Resources();
                NodeList children = resourcesElement.getChildNodes();
                for (int j = 0; j < children.getLength(); j++) {
                    Node childNode = children.item(j);
                    if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                        Element child = (Element) childNode;
                        if (child.getLocalName().equals("Resource")) {
                            Resource resource=new Resource();
                            resource.setPath(child.getAttribute("path"));
                            rs.getResourceList().add(resource);
                        }
                    }
                }
                
                setting.setResources(rs);
            }
        }
        NodeList forms = element.getElementsByTagNameNS("*", "Forms");
        for (int i = 0; i < forms.getLength(); i++) {
        	System.out.println("-------------form:"+forms.item(i));
            Node formsNode = forms.item(i);
            if (formsNode.getNodeType() == Node.ELEMENT_NODE) {
                Element formsElement = (Element) formsNode;
                Forms fs=new Forms();
                fs.setFormList(new ArrayList<Form>());
                NodeList children = formsElement.getChildNodes();
                for (int j = 0; j < children.getLength(); j++) {
                    Node childNode = children.item(j);
                    if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                        Element child = (Element) childNode;
                        if (child.getLocalName().equals("Form")) {
                            Form form=new Form();
                            if(child.getAttribute("class").length()>=0)form.set_class(child.getAttribute("class"));
                            form.setName(child.getAttribute("name"));
                            if(child.getAttribute("type").length()>0)form.setType(child.getAttribute("type"));
                            fs.getFormList().add(form);
                        }
                    }
                }
                
                setting.setForms(fs);
            }
        }

        NodeList globalNodes = element.getElementsByTagNameNS("*", "Global");
        for (int i = 0; i < globalNodes.getLength(); i++) {
            Node globalNode = globalNodes.item(i);
            if (globalNode.getNodeType() == Node.ELEMENT_NODE) {
                Element globalElement = (Element) globalNode;
                Global global=new Global();

                NodeList children = globalElement.getChildNodes();
                for (int j = 0; j < children.getLength(); j++) {
                    Node childNode = children.item(j);
                    if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                        Element child = (Element) childNode;
                        if (child.getLocalName().equals("ActionException")) {
                            ActionException ae=new ActionException();
                            ae.setActionForward(child.getAttribute("actionForward"));
                            ae.setId(child.getAttribute("id"));
                            ae.setType(child.getAttribute("type"));
                            global.getActionExceptions().add(ae);
                        } else if(child.getLocalName().equals("ProcessException")){
                            ProcessException pe=new ProcessException();
                            if(child.getAttribute("exec").length()>0)pe.setExec(child.getAttribute("exec"));
                            pe.setId(child.getAttribute("id"));
                            pe.setType(child.getAttribute("type"));
                            if(child.getAttribute("view").length()>0)pe.setView(child.getAttribute("view"));
                            if(child.getAttribute("viewType").length()>0)pe.setViewType(child.getAttribute("viewType"));
                            global.getProcessExceptions().add(pe);
                        }
                    }
                }

                setting.setGlobal(global);
            }
        }
        return setting;
    }
}
